#ifndef UNITTESTER_CPP_JM_20130111
#define UNITTESTER_CPP_JM_20130111

#include "UnitTester.h"

namespace jmlib {
	

	UnitTester* UnitTester::getInstance() {
		static UnitTester tester;
		return &tester;
	}

	UnitTester::~UnitTester() {
		for (size_t i = 0; i < tests_.size(); ++i) {
			delete tests_[i];
		}
	}

	void UnitTester::registerTest(UnitTest* t) {
		tests_.push_back(t);
	}


	void UnitTester::testFail(const std::string& message, 
		const std::string& testName, const std::string& testFile, 
		size_t testLine) {

			++detectedFailCount_;

			errorMessage(message, testName, testFile, testLine);

			if (firstTestFailStopTesting_) {
				throw FirstTestFailException();
			}

	}
	void UnitTester::errorMessage(const std::string& message, 
		const std::string& testName, const std::string& testFile, 
		size_t testLine) {

			getOutput() << "Unit test fails:" << std::endl
				<< "\tCondition: " << message << std::endl 
				<< "\tTest: " << testName << std::endl
				<< "\tFile: " << testFile << std::endl
				<< "\tLine: " << testLine << std::endl
				<< "=============================================" << std::endl;

	}

	void UnitTester::runTests() {
		size_t testIndex = 0;
		while (testIndex < tests_.size()) {
			try {
				for (; testIndex < tests_.size(); ++testIndex) {
					tests_[testIndex]->runTest();
				}
			}
			catch (const FirstTestFailException&) {
				testIndex = tests_.size(); // Ukoncenie testovania.
			}
		}
		testSummary();
	}

	void UnitTester::testSummary() {
		const char* fs = detectedFailCount_ == 1 ? "" : "s";
		const char* ts = performedTestCount_== 1 ? "" : "s";
		getOutput() << std::endl << "Detected " << detectedFailCount_ << 
			" fail" << fs << " in " << performedTestCount_ 
			<< " test" << ts << "." << std::endl << std::endl;
	}
} // namespace jmlib

#endif
